﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data;

using System.Threading;
using System.IO.Ports;

namespace ControlCenterService
{
    public class SerialOverUSBTools
    {
        public SerialOverUSBTools()
        {
            initialize();
        }




        #region NewMessageReceived Event and Delegate
        public class NewMessageReceivedEventArgs : System.ComponentModel.CancelEventArgs
        {
            public NewMessageReceivedEventArgs(string Key)
            {
                this.m_Key = Key;
            }
            private string m_Key;
            public string Key
            {
                get
                {
                    return m_Key;
                }
                set
                {
                    m_Key = value;
                }
            }
        }


        public delegate void NewMessageReceivedHandler(object sender,
          NewMessageReceivedEventArgs EventArgsParam);


        public event NewMessageReceivedHandler NewMessageReceived;


        protected virtual void OnNewMessageReceived(NewMessageReceivedEventArgs EventArgsParam)
        {
            NewMessageReceivedHandler EventHandler = NewMessageReceived;
            if (NewMessageReceived != null)
            {
                //if (NewMessageReceived.Target is
                //    System.Windows.Forms.Control)
                //{
                //    // since the event sink is a control, use Invoke to 
                //    // ensure it is called on the UI thread
                //    System.Windows.Forms.Control targetForm = NewMessageReceived.Target
                //        as System.Windows.Forms.Control;
                //    targetForm.Invoke(NewMessageReceived,
                //        new object[] { this, EventArgsParam });
                //}
                //else
                {
                    NewMessageReceived(this, EventArgsParam);
                }
            }
        }
        #endregion
      
      
      
  

        string comPort = "COM4";
        string baudRate = "9600";
        string dataBits = "8";
        string stopBits = "1";
        string parity = "None";
        string flowControl = "None";
        string Xon = "11";
        string Xoff = "13";

        public System.IO.Ports.SerialPort serialPort1;

        public string receiveBuffer = string.Empty;

        private void initialize()
        {
            getComPortListAndPickFirstOne();
            serialPort1 = new SerialPort();
            serialPort1.DataReceived += new
                 SerialDataReceivedEventHandler(serialPort1_DataReceived);
            openConnection();
        }

        private void shutdown()
        {
            if (serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Close();
                }
                catch (System.Exception)
                {
                    //MessageBox.Show("Failed to close selected port.");
                }
            }
            serialPort1.DataReceived -= new
                             SerialDataReceivedEventHandler(serialPort1_DataReceived);
        }


        private void getComPortListAndPickFirstOne()
        {
            string[] AvailableCOMPorts;

            //// Clear combobox
            //this.comboBox1.Items.Clear();
            //this.comboBox1.Text = "";

            // Determine the COM ports currently available
            AvailableCOMPorts = System.IO.Ports.SerialPort.GetPortNames();

            if (AvailableCOMPorts.Count() > 0)
            {
                // take first one if there is one
                comPort = AvailableCOMPorts[0];
            }

            for (int j = 0; j < AvailableCOMPorts.Length; j++)
            {
                //// Add it to the combo box.
                //this.comboBox1.Items.Add(AvailableCOMPorts[j]);
            }

        }

        private void openConnection()
        {
            if (comPort.CompareTo(System.String.Empty) != 0)
            {

                // Set port name to that selected in the combobox
                serialPort1.PortName = comPort;

                // Set port parameters
                serialPort1.BaudRate = Convert.ToInt32(baudRate);
                serialPort1.DataBits = Convert.ToInt32(dataBits);
                serialPort1.StopBits = System.IO.Ports.StopBits.One;
                switch (stopBits)
                {
                    case "1":
                        serialPort1.StopBits = System.IO.Ports.StopBits.One;
                        break;

                    case "2":
                        serialPort1.StopBits = System.IO.Ports.StopBits.Two;
                        break;

                    default:
                        serialPort1.StopBits = System.IO.Ports.StopBits.One;
                        break;
                }

                switch (parity)
                {
                    case "None":
                        serialPort1.Parity = System.IO.Ports.Parity.None;
                        break;

                    case "Odd":
                        serialPort1.Parity = System.IO.Ports.Parity.Odd;
                        break;

                    case "Even":
                        serialPort1.Parity = System.IO.Ports.Parity.Even;
                        break;

                    case "Mark":
                        serialPort1.Parity = System.IO.Ports.Parity.Mark;
                        break;

                    case "Space":
                        serialPort1.Parity = System.IO.Ports.Parity.Space;
                        break;

                    default:
                        serialPort1.Parity = System.IO.Ports.Parity.None;
                        break;
                }

                switch (parity)
                {
                    case "None":
                        serialPort1.Handshake = System.IO.Ports.Handshake.None;
                        break;

                    case "RTS-CTS":
                        serialPort1.Handshake = System.IO.Ports.Handshake.RequestToSend;
                        break;

                    case "Xon-Xoff":
                        serialPort1.Handshake = System.IO.Ports.Handshake.XOnXOff;
                        break;

                    default:
                        serialPort1.Handshake = System.IO.Ports.Handshake.None;
                        break;
                }


                // Try to open the serial port
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception)
                {
                    //MessageBox.Show("Failed to open selected port.\nIs it open in another application?\n(" + ")");
                }
                finally
                {
                    // If we have successfully opened the port, enable/disable buttons
                    if (serialPort1.IsOpen)
                    {
                        serialPort1.RtsEnable = true;
                        serialPort1.DtrEnable = true;

                        // Set write timeout
                        serialPort1.WriteTimeout = 5000;

                    }
                }
            }
        }

        private void closeConnection(object sender, EventArgs e)
        {
            try
            {
                // Close the serial port
                serialPort1.Close();
            }
            catch (System.Exception)
            {
                //MessageBox.Show("Failed to close port.");
            }
        }




        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            OnNewMessageReceived(new NewMessageReceivedEventArgs(serialPort1.ReadExisting()));
            // This event handler fires each time data is received by the serial port.
            // Read available data from the serial port and display it on the form.
            // This event does not run in the UI thread, so need to 
            // use delegate function

            //string strErg = serialPort1.ReadExisting();
            //receiveBuffer += strErg;
            ////////this.BeginInvoke(new EventHandler(delegate
            ////////{
            ////////    SetTheText(strErg);

            ////////}));
            ////////Application.DoEvents();
        }


        private void SetTheText(string strText)
        {
            //textBox2.Text += strText;
        }


        public void sendChar(char sourceChar)
        {
            // If the port is closed, don't try to send a character.
            if (!serialPort1.IsOpen) return;

            // If the port is Open, declare a char[] array with one element.
            char[] buff = new char[1];

            // Load element 0 with the key character.
            buff[0] = sourceChar;

            try
            {
                // Send the one character buffer.
                serialPort1.Write(buff, 0, 1);
            }
            catch (System.Exception)
            {
                //MessageBox.Show("Failed to write to port.");
            }
        }


    }
}
